package com.njtech.pet.service.impl;

import com.njtech.pet.constant.Constant;
import com.njtech.pet.dao.*;
import com.njtech.pet.entity.*;
import com.njtech.pet.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import java.text.SimpleDateFormat;
import java.util.*;
import static com.njtech.pet.constant.Constant.Bill.*;

/**
 * Author:cw
 * Date:2020-03-20 19:37
 * Description:MemberService中方法的实现
 */

@Service
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public class MemberServiceImpl implements MemberService {

    @Autowired
    @Resource(name = "billDao")
    private BillDao billDao;
    @Resource(name = "userDao")
    private UserDao userDao;
    @Resource(name = "itemDao")
    private ItemDao itemDao;
    @Resource(name = "actionDao")
    private ActionDao actionDao;


    /**
     * 计算对应会员的等级的价格或者积分,type = 1时计算折扣价格，type = 2时计算积分
     * @param type
     * @param PC 所要计算的积分或者价格的值
     * @param user 对应用户
     * @return 返回计算后的结果
     */
    @Override
    public double levelPC(int type, double PC, User user){
        double finalPC = PC;

        switch(user.getLevel()){
            case 1:
                if(type == 1) {
                    finalPC = PC * Constant.Member.LEVEL1.getDiscount();
                }
                else if(type == 2) {
                    finalPC = PC * Constant.Member.LEVEL1.getCreditPercent();
                }
                break;
            case 2:
                if(type == 1) {
                    finalPC = PC * Constant.Member.LEVEL2.getDiscount();
                }
                else if(type == 2) {
                    finalPC = PC * Constant.Member.LEVEL2.getCreditPercent();
                }
                break;
            case 3:
                if(type == 1) {
                    finalPC = PC * Constant.Member.LEVEL3.getDiscount();
                }
                else if(type == 2) {
                    finalPC = PC * Constant.Member.LEVEL3.getCreditPercent();
                }
                break;
            case 4:
                if(type == 1) {
                    finalPC = PC * Constant.Member.LEVEL4.getDiscount();
                }
                else if(type == 2) {
                    finalPC = PC * Constant.Member.LEVEL4.getCreditPercent();
                }
                break;
            case 5:
                if(type == 1) {
                    finalPC = PC * Constant.Member.LEVEL5.getDiscount();
                }
                else if(type == 2) {
                    finalPC = PC * Constant.Member.LEVEL5.getCreditPercent();
                }
                break;
        }
        return finalPC;
    }
    /**
     *用户购买保险所花费的实际金额计算
     * @param item 所购买的保险项目
     * @param user 购买用户
     * @param coupon 购买用户的优惠卷
     * @return 返回折扣后的价格
     */
    @Override
    public double priceDiscount(Item item, User user, Item coupon) {
        double finalPrice = item.getPrice();
        if(coupon != null)
        {
            if(useCoupon(user,coupon,item) == 1) {
                //先去掉优惠卷的价格
                finalPrice = finalPrice - coupon.getPrice();
            }

        }
        //计算会员价
        finalPrice = levelPC(1,finalPrice,user);
        return finalPrice;
    }

    /**
     * 用户签到
     * @param user 进行签到的用户
     * @return 返回签到是否成功
     */

    @Override
    public boolean signIn(User user) {
        if(ifFirstSignInDaily(user)) {
            boolean flag = false;
            Integer credit = user.getCredit();
            Integer checkCredit = credit;
            credit += (int) levelPC(2, Constant.Credit.DAILY_CREDIT.getValue(), user);
            if (checkCredit != credit) {
                user.setCredit(credit);
                ifUpgradeMember(user);
                //填写充值会员的bill
                Bill bill = new Bill();
                bill.setUser(user);
                Item signInItem = itemDao.selectByType(Constant.signInItem.getType()).get(0);
                bill.setItem(signInItem);
                bill.setCreateDate(new Date());
                //每日签到的bill状态为：永久有效
                bill.setState(STATE_PERMANENT.getValue());
                //修改订单类别为：每日首签
                bill.setType(Constant.Bill.TYPE_FIRST_SIGN_IN.getValue());
                //记录用户积分变化
                bill.setCredit(Constant.signInItem.getCredit());
                bill.setPrice(0.0);
                bill.setBuyWay("每日首签");
                bill.setProof("已完成每日首签");

                //设置生效日期和截止日期
                bill.setUseDate(new Date());
                Calendar cal = Calendar.getInstance();
                Date expireDate = new Date();
                cal.setTime(expireDate);
                cal.add(Calendar.DATE, Constant.signInItem.howLong);
                expireDate = cal.getTime();
                bill.setExpireDate(expireDate);
                //统一设置优惠卷的pet和person属性为null用于优惠卷的bill生成
                bill.setPet(null);
                bill.setBuyer(null);
                bill.setInsured(null);
                bill.setRemark("进行用户今日的首次签到");
                int num = billDao.insert(bill);

                //添加Action表中信息
                Action action = new Action();
                action.setUser(user);
                action.setItem(signInItem);
                action.setAction(Constant.Action.ACTION_SIGN.getValue());
                action.setCreateDate(new Date());
                action.setState(Constant.Action.STATE_VALID.getValue());
                action.setUpdateDate(new Date());
                action.setRemark("用户进行每日首次签到");
                actionDao.insert(action);
                if (num == 1) {
                    flag = true;
                }
                return flag;
            } else {
                return flag;
            }
        }
        return false;

    }

    /**
     * 判断用户是否能够首签
     * @param user 用户
     * @return 返回能否首签
     */
    @Override
    public boolean ifFirstSignInDaily(User user) {
        List<Bill> bList = billDao.selectByUser(user,Constant.Bill.STATE_PERMANENT.getValue(),Constant.Bill.TYPE_FIRST_SIGN_IN.getValue(),null,null);
        //开通用户时第一次签到
        if(bList == null || bList.isEmpty()) {
            return true;
        }
        else {
            Date now = new Date();
            //因为bList所得到的结果是按时间先后排序的，所以数组的第一个数据是最近的一次签到
            //比较最近一次签到的过期时间和当前时间来判断是否可以签到
            if (now.after(bList.get(0).getExpireDate())) {
                return true;
            }
            return false;
        }
    }

    /**
     * 用户领取优惠卷,当用户积分小于优惠卷所需积分时返回false
     * @param user 领取者账号
     * @param item 优惠卷
     * @return 返回是否成功
     */
    @Override
    public boolean getCoupon(User user, Item item) {
        boolean flag = false;
        if(item.getType().equals(Constant.Item.TYPE_COUPON.getValue())) {
            if (user.getCredit() < item.getCredit()) {
                return flag;
            } else {
                Bill bill = new Bill();
                bill.setUser(user);
                bill.setItem(item);
                bill.setCreateDate(new Date());
                //修改优惠卷的状态改为：优惠券未使用
                bill.setState(STATE_COUPON_UNUSED.getValue());
                //修改订单类别为：领取优惠券
                bill.setType(Constant.Bill.TYPE_COUPON.getValue());
                //记录用户积分变化
                bill.setCredit(-1 * item.getCredit());
                bill.setPrice(0.0);
                bill.setBuyWay("积分兑换");
                bill.setProof("用户积分已扣除");

                //设置生效日期和截止日期
                bill.setUseDate(new Date());
                Calendar cal = Calendar.getInstance();
                Date expireDate = new Date();
                cal.setTime(expireDate);
                cal.add(Calendar.DATE, item.getHowLong());
                expireDate = cal.getTime();
                bill.setExpireDate(expireDate);

                //统一设置优惠卷的pet和person属性为null用于优惠卷的bill生成
                bill.setPet(null);
                bill.setBuyer(null);
                bill.setInsured(null);
                //说明
                bill.setRemark("兑换优惠卷");
                int num = billDao.insert(bill);

                userDao.updateUserCredit(user.getId(),bill.getCredit());
                if (num == 1) {
                    flag = true;
                }

                return flag;
            }
        }
        else {
            return flag;
        }
    }

    /**
     * 开通会员，根据用户积分来确定会员等级
     * @param user
     * @return 开通成功返回true,失败返回false，在调用该方法前需要判断是否付款成功，成功时才调用
     */

    @Override
    public boolean getMember(User user) {
        boolean flag = false;
        if(user.getLevel() == 0) {
            if (user.getCredit() < 50) {
                user.setLevel(1);
                user.setRole(Constant.Member.LEVEL1.getValue());
            } else if (user.getCredit() < 200) {
                user.setLevel(2);
                user.setRole(Constant.Member.LEVEL2.getValue());
            } else if (user.getCredit() < 400) {
                user.setLevel(3);
                user.setRole(Constant.Member.LEVEL3.getValue());
            } else if (user.getCredit() < 800) {
                user.setLevel(4);
                user.setRole(Constant.Member.LEVEL4.getValue());
            } else {
                user.setLevel(5);
                user.setRole(Constant.Member.LEVEL5.getValue());
            }
        }
            Bill bill = new Bill();
            //填写充值会员的bill
            bill.setUser(user);
            Item topUpItem = itemDao.selectByType(Constant.memberItem.getType()).get(0);
            bill.setItem(topUpItem);
            bill.setCreateDate(new Date());
            //充值会员的bill状态为：永久有效
            bill.setState(STATE_PERMANENT.getValue());
            //修改订单类别为：充值会员
            bill.setType(Constant.Bill.TYPE_TOPUPMEMBER.getValue());
            //记录用户积分变化
            bill.setCredit(Constant.memberItem.getCredit());
            bill.setPrice(Constant.memberItem.getPrice());
            bill.setBuyWay("充值购买");
            bill.setProof("已通过支付宝购买成功");

            //设置生效日期和截止日期
            bill.setUseDate(new Date());
            Calendar cal = Calendar.getInstance();
            Date expireDate = new Date();
            cal.setTime(expireDate);
            cal.add(Calendar.DATE, Constant.memberItem.howLong);
            expireDate = cal.getTime();
            bill.setExpireDate(expireDate);

            //设置用户的会员过期时间
            Date dueDate = user.getDue();
            cal.setTime(dueDate);
            cal.add(Calendar.DATE, Constant.memberItem.howLong);
            dueDate = cal.getTime();
            user.setDue(dueDate);
            Integer credit = user.getCredit();
            credit += Constant.memberItem.getCredit();
            user.setCredit(credit);
            ifUpgradeMember(user);

            //统一设置优惠卷的pet和person属性为null用于优惠卷的bill生成
            bill.setPet(null);
            bill.setBuyer(null);
            bill.setInsured(null);
            bill.setRemark("进行会员的充值操作");

            int num = billDao.insert(bill);
            if (num == 1){
                flag = true;
            }
            return flag;
    }

    /**
     * 判断是否是会员
     * @param user
     * @return false为不是，true为是
     */
    @Override
    public boolean ifMember(User user) {
        if(user.getLevel() == 0){
            return false;
        }
        else{
            //找出所有充值会员的bill，选取其中最新的bill，判断其到期时间与当前时间的大小
            List<Bill> bList = billDao.selectByUser(user,Constant.Bill.STATE_PERMANENT.getValue(),Constant.Bill.TYPE_TOPUPMEMBER.getValue(),null,null);
            if(bList != null && !bList.isEmpty()){
                Bill bill = bList.get(bList.size()-1);
                //过期返回false并且修改user中level的等级
                if(bill.getExpireDate().compareTo(new Date()) == -1){
                    user.setLevel(0);
                    user.setRole(Constant.Member.LEVEL0.getValue());
                    userDao.updateByUserId(user);
                    return false;
                }
            }
            return true;
        }
    }

    /**
     * 判断优惠卷是否过期
     * @param bill
     * @return 如果过期改变优惠卷的状态，返回true
     */
    @Override
    public boolean ifCouponExpire(Bill bill) {
        Date nowDate = new Date();
        if(bill != null) {
            Date expireDate = bill.getExpireDate();
            //compareTo函数返回值：1表示指定数大于参数，-1表示指定数小于参数，0表示等于
            if (nowDate.compareTo(expireDate) != 1) {
                return false;
            } else {
                bill.setState(Constant.Bill.STATE_COUPON_EXPIRED.getValue());
                billDao.updateByBillId(bill);
                return true;
            }
        }
        return true;
    }

    /**
     * 在积分变动的情况下判断用户的会员等级是否发生改变
     * @param user 判断的用户
     * @return 返回是否发生了变化
     */
    @Override
    public boolean ifUpgradeMember(User user) {
        boolean flag = false;
        switch(user.getLevel()){
            case 1:
                if(user.getCredit() > Constant.Member.LEVEL1.getUpper()){
                    user.setLevel(user.getLevel()+1);
                    user.setRole(Constant.Member.LEVEL2.getValue());
                }
            case 2:
                if(user.getCredit() > Constant.Member.LEVEL2.getUpper()){
                    user.setLevel(user.getLevel()+1);
                    user.setRole(Constant.Member.LEVEL3.getValue());
                }
            case 3:
                if(user.getCredit() > Constant.Member.LEVEL3.getUpper()){
                    user.setLevel(user.getLevel()+1);
                    user.setRole(Constant.Member.LEVEL4.getValue());
                }
            case 4:
                if(user.getCredit() > Constant.Member.LEVEL4.getUpper()){
                    user.setLevel(user.getLevel()+1);
                    user.setRole(Constant.Member.LEVEL5.getValue());
                }
                break;
        }
        int num = userDao.updateByUserId(user);
        if(num == 1){
            flag = true;
        }
        return flag;
    }

    /**
     * 展示返回会员等级的文字表述（用于展示user内容的页面）
     * @param user
     * @return 返回会员等级的文字描述
     */
    @Override
    public String showLevel(User user){
        int num = user.getLevel();
        String level = Constant.Member.LEVEL0.getValue();
        switch (num){
            case 1:
                level = Constant.Member.LEVEL1.getValue();
                break;
            case 2:
                level = Constant.Member.LEVEL2.getValue();
                break;
            case 3:
                level = Constant.Member.LEVEL3.getValue();
                break;
            case 4:
                level = Constant.Member.LEVEL4.getValue();
                break;
            case 5:
                level = Constant.Member.LEVEL5.getValue();
                break;
        }
        return level;
    }

    /**
     * 展示对应用户的state为优惠卷未使用的所有优惠卷
     * @param user
     * @return 返回优惠卷数组，没有返回null
     */
    @Override
    public List<Item> showMyCoupon(User user){
        List<Bill> bList = billDao.selectByUser(user,STATE_COUPON_UNUSED.getValue(), TYPE_COUPON.getValue(), null, null);
        Integer size = bList.size();
        for(int i = 0;i < size;i++)
        {
            ifCouponExpire(bList.get(i));
        }
        bList = billDao.selectByUser(user,STATE_COUPON_UNUSED.getValue(), TYPE_COUPON.getValue(), null, null);
        if(bList != null && !bList.isEmpty()) {
            List<Item> iList = new ArrayList();
            Bill tempBill = new Bill();
            Item tempItem = new Item();
            for (int i = 0; i < size; i++) {
                tempBill = bList.get(i);
                tempItem = tempBill.getItem();
                iList.add(tempItem);
            }
            return iList;
        }
        else{
            return null;
        }
    }

    /**
     * 用于会员界面中的到期时间显示
     * @param user
     * @return 到期时间
     */
    @Override
    public String showExpireDate(User user){
        List<Bill> bList = billDao.selectByUser(user,Constant.Bill.STATE_PERMANENT.getValue(),Constant.Bill.TYPE_TOPUPMEMBER.getValue(),null,null);
        Bill bill = bList.get(bList.size()-1);
        Date date = bill.getExpireDate();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        String strDate = sf.format(date);
        return strDate;
    }

    /**
     * 显示用户对应VIP等级的等级名、下限、上限、折扣系数、积分系数
     * @param user
     * @return 返回对应list数组
     */
    @Override
    public List<String> showLevelInfo(User user){
        List<String> list = new ArrayList<>();
        Integer level = user.getLevel();
        String name;
        Integer lower;
        Integer upper;
        Double discount;
        Double creditPercent;
        switch (level){
            case 1:
                name = Constant.Member.LEVEL1.getValue();
                lower = Constant.Member.LEVEL1.getLower();
                upper = Constant.Member.LEVEL1.getUpper();
                discount = Constant.Member.LEVEL1.getDiscount();
                creditPercent = Constant.Member.LEVEL1.getCreditPercent();
                break;
            case 2:
                name = Constant.Member.LEVEL2.getValue();
                lower = Constant.Member.LEVEL2.getLower();
                upper = Constant.Member.LEVEL2.getUpper();
                discount = Constant.Member.LEVEL2.getDiscount();
                creditPercent = Constant.Member.LEVEL2.getCreditPercent();
                break;
            case 3:
                name = Constant.Member.LEVEL3.getValue();
                lower = Constant.Member.LEVEL3.getLower();
                upper = Constant.Member.LEVEL3.getUpper();
                discount = Constant.Member.LEVEL3.getDiscount();
                creditPercent = Constant.Member.LEVEL3.getCreditPercent();
                break;
            case 4:
                name = Constant.Member.LEVEL4.getValue();
                lower = Constant.Member.LEVEL4.getLower();
                upper = Constant.Member.LEVEL4.getUpper();
                discount = Constant.Member.LEVEL4.getDiscount();
                creditPercent = Constant.Member.LEVEL4.getCreditPercent();
                break;
            case 5:
                name = Constant.Member.LEVEL5.getValue();
                lower = Constant.Member.LEVEL5.getLower();
                upper = Constant.Member.LEVEL5.getUpper();
                discount = Constant.Member.LEVEL5.getDiscount();
                creditPercent = Constant.Member.LEVEL5.getCreditPercent();
                break;
            default:
                name = Constant.Member.LEVEL0.getValue();
                lower = 0;
                upper = 1000;
                discount = Constant.Member.LEVEL0.getDiscount();
                creditPercent = Constant.Member.LEVEL0.getCreditPercent();
        }
        list.add(0,name);
        list.add(1, ""+lower);
        list.add(2, ""+upper);
        list.add(3, ""+discount);
        list.add(4, ""+creditPercent);
        return list;
    }

    /**
     * 返回现有的所有有效优惠卷
     * @param user
     * @return 非会员时返回null
     */
    @Override
    public List<Item> showCoupon(User user){
        if(ifMember(user)){
            Item coupon = new Item();
            coupon.setType(Constant.Item.TYPE_COUPON.getValue());
            List<Item> itemList = itemDao.selectElastically(coupon,null,null,null,null,null,null);
            return itemList;
        }
        else{
            return null;
        }
    }

    /**
     * 购买保险使用优惠卷时，生成对应的bill
     * @param user 优惠券使用人
     * @param coupon 所使用的优惠券
     * @param item 对应保险
     * @return 返回生成的bill数量:1表示使用成功，0表示使用失败，-1表示输入的格式有问题（user、coupon、item中有为null的），-2表示优惠券过期或优惠券状态有错
     */
    @Override
    public Integer useCoupon(User user, Item coupon, Item item) {
        if(user != null && coupon != null && item != null) {
            //查询出对应的优惠券，且账单中的state为"优惠券未使用"
            List<Bill> bList = billDao.selectByUserAndCoupon(user,coupon,Constant.Bill.STATE_COUPON_UNUSED.getValue());
            if(!bList.isEmpty()) {
                Bill bill = bList.get(0);
                if (!ifCouponExpire(bill)) {
                    //在bill.remark中显示所对应使用的保险
                    bill.setRemark("已使用于ID为:" + item.getId() + "的保险");
                    //设置bill的type为"使用优惠券"，state为"优惠券已使用"
                    bill.setType(Constant.Bill.TYPE_USE_COUPON.getValue());
                    bill.setState(Constant.Bill.STATE_COUPON_USED.getValue());
                    //修改时间
                    bill.setUseDate(new Date());
                    return billDao.updateByBillId(bill);
                }
            }
            return -2;
        }
        else {
            return -1;
        }
    }

    /**
     * 管理界面展示所有优惠卷信息
     * @return
     */
    @Override
    public List<Item> showAllCoupon() {
        List<Item> list = itemDao.selectByType(Constant.Item.TYPE_COUPON.getValue());
        return list;
    }

    /**
     * 管理界面添加优惠卷
     * @param coupon
     * @return 是否成功
     */
    @Override
    public boolean insertCoupon(Item coupon) {
        int flag = itemDao.insert(coupon);
        if(flag == 1){
            return true;
        }
        return false;
    }

    /**
     * 管理界面修改优惠券信息
     * @param coupon
     * @return 是否成功
     */
    @Override
    public boolean updateCoupon(Item coupon) {
        int flag = itemDao.updateByItemId(coupon);
        if(flag == 1){
            return true;
        }
        return false;
    }
}
